package main

import (
	"log"
	"go-try/pool/pool"
	"sync/atomic"
	"io"
	"sync"
	"time"
)

type dbConnection struct {
	ID int32
}

const (
	maxGoroutines = 25
	pooledResource = 2
)

var connCount int32

func (c *dbConnection)Close() error{
	log.Println("Close connection: ", c.ID)
	return nil
}
//todo 1 difference between structVar and &structVar
func createConnection()(io.Closer, error){
	id := atomic.AddInt32( &connCount, 1 )
	log.Println("Create Connection: %d", connCount)
	return &dbConnection{id}, nil
}

func main(){
	log.Printf("test type of pooled resource %T", pooledResource)
	p := pool.New(createConnection, pooledResource)

	//todo how to define waitGroup
	var wg sync.WaitGroup
	wg.Add(maxGoroutines)

	for i:=0; i<maxGoroutines; i++{
		go func(q int) {
			performQuery(p, q)
			wg.Done()
		}(i)
	}
	wg.Wait()
	p.Close()
}

func performQuery(p *pool.Pool, q int) {
	r,err := p.Acquire()
	if err!=nil{
		log.Printf("Query[%d] error: %v\n", q, err)
		return
	}
	time.Sleep(time.Duration(3 * time.Second))
	p.Release(r)
	//todo why have to use Assertion
	log.Printf("Query[%d] Connection[%d]\n",q, r.(*dbConnection).ID)
}